package com.miyake.dsp.osa.method;

import java.util.HashMap;
import java.util.Map;

import com.miyake.dsp.common.CommonTool;

public class Extractor {
	public int getiMaskStart() {
		return iMaskStart;
	}

	public int getiMaskEnd() {
		return iMaskEnd;
	}

	public int getiStart() {
		return iStart;
	}

	public int getiEnd() {
		return iEnd;
	}

	public InterpolationType getInterpolationType() {
		return interpolationType;
	}

	public void setInterpolationType(InterpolationType interpolationType) {
		this.interpolationType = interpolationType;
	}

	public enum InterpolationType {
		Point, Area
	};
	
	private Map<String, double[]> map = new HashMap<String, double[]>();
	private double[] base;
	private int iMaskStart;
	private int iMaskEnd;
	private int iStart;
	private int iEnd;
	private InterpolationType interpolationType = InterpolationType.Point;
	private double left;
	private double right;
	
	public Extractor(double[] base) {
		this.base = base;
	}
	
	public void setArea(double fittingStart, double fittingEnd, double maskStart, double maskEnd) {
		this.iMaskStart = CommonTool.toIndex(base, maskStart, CommonTool.RoundType.Round);
		this.iMaskEnd = CommonTool.toIndex(base, maskEnd, CommonTool.RoundType.Round);
		this.iStart = CommonTool.toIndex(base, fittingStart, CommonTool.RoundType.Round);
		this.iEnd = CommonTool.toIndex(base, fittingEnd, CommonTool.RoundType.Round);
		this.interpolationType = InterpolationType.Area;
	}
	
	public void setPoint(double left, double right) {
		this.left = left;
		this.right = right;
		this.iStart = CommonTool.toIndex(base, left, CommonTool.RoundType.Round);
		this.iEnd = CommonTool.toIndex(base, right, CommonTool.RoundType.Round);
		this.interpolationType = InterpolationType.Point;
	}
	
	public void addData(double[] data, String id) {
		this.map.put(id, data);
	}
	
	public double[] getFittingDataX() {
		if (this.interpolationType.equals(InterpolationType.Area)) {
			return extractArea(this.base);
		}
		else if (this.interpolationType.equals(InterpolationType.Point)) {
			return extractPoint(this.base);
		}
		return null;
	}
	
	public double[] getBaseToBeFilled() {
		int size = iEnd - iStart + 1;
		double[] ret = new double[size];
		for (int i = iStart; i <= iEnd; i++) {
			ret[i-iStart] = this.base[i];
		}
		return ret;
	}
	
	public double[] getExtractedData(String id) {
		int size = iEnd - iStart + 1;
		double[] ret = new double[size];
		double[] data = this.map.get(id);
		for (int i = this.iStart; i < this.iEnd; i++) {
			ret[i - iStart] = data[i];
		}
		return ret;
	}
	
	public double[] getFittingData(String id) {
		if (this.interpolationType.equals(InterpolationType.Area)) {
			return extractArea(map.get(id));
		}
		else if (this.interpolationType.equals(InterpolationType.Point)) {
			return extractPoint(map.get(id));
		}
		return null;
	}
	
	private double[] extractPoint(double[] original) {
		double[] ret = new double[2];

		ret[0] = CommonTool.getInterpolated(base, original, this.left);
		ret[1] = CommonTool.getInterpolated(base, original, this.right);
		
		return ret;
	}
	
	private double[] extractArea(double[] original) {
		int size = (iEnd - iStart) - (iMaskEnd - iMaskStart) + 2;
		double[] ret = new double[size];
		int index = 0;
		for (int i = iStart; i <= iEnd; i++) {
			if (i < (iMaskStart+1) || i > (iMaskEnd-1)) {
				ret[index] = original[i];
				index++;
			}
		}	
		return ret;	
	}
}
